// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//                            avtPLYFileFormat.C                           //
// ************************************************************************* //

#include <avtPLYFileFormat.h>

#include <string>
#include <vtkPolyData.h>
#include <vtkPLYReader.h>

#include <DebugStream.h>
#include <ImproperUseException.h>
#include <InvalidVariableException.h>
#include <InvalidFilesException.h>
#include <avtDatabase.h>
#include <DBOptionsAttributes.h>

using     std::string;

// ****************************************************************************
//  Method: avtPLYFileFormat constructor
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

avtPLYFileFormat::avtPLYFileFormat(const char *filename, const DBOptionsAttributes*)
    : avtSTSDFileFormat(filename)
{
    dataset = NULL;
    readInDataset = false;
    checkedFile = false;
}

// ****************************************************************************
//  Method: avtPLYFileFormat deconstructor
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

avtPLYFileFormat::~avtPLYFileFormat()
{
    if (dataset != NULL)
    {
        dataset->Delete();
        dataset = NULL;
    }
}


// ****************************************************************************
//  Method: avtPLYFileFormat::FreeUpResources
//
//  Purpose:
//      When VisIt is done focusing on a particular timestep, it asks that
//      timestep to free up any resources (memory, file descriptors) that
//      it has associated with it.  This method is the mechanism for doing
//      that.
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

void
avtPLYFileFormat::FreeUpResources(void)
{
    debug4 << "PLY file " << filename 
           << " forced to free up resources." << endl;

    if (dataset != NULL)
    {
        dataset->Delete();
        dataset = NULL;
    }

    readInDataset = false;
}


// ****************************************************************************
//  Method: avtPLYFileFormat::PopulateDatabaseMetaData
//
//  Purpose:
//      This database meta-data object is like a table of contents for the
//      file.  By populating it, you are telling the rest of VisIt what
//      information it can request from you.
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

void
avtPLYFileFormat::PopulateDatabaseMetaData(avtDatabaseMetaData *md)
{
    if (avtDatabase::OnlyServeUpMetaData())
    {
        if (!checkedFile)
        {
            ReadInDataset();
            if (!dataset ||
                dataset->GetNumberOfCells() == 0 ||
                dataset->GetNumberOfPoints() == 0)
            {
                EXCEPTION2(InvalidFilesException,filename,
                           "Empty dataset assumed to be erroneous file."); 
            }
            dataset->Delete();
            dataset = NULL;
            readInDataset = false;
            checkedFile = true;
        }
    }

    int spat = 3;
    int topo = 2;

    avtMeshType type = AVT_SURFACE_MESH;

    AddMeshToMetaData(md, "PLY_mesh", type, NULL, 1, 0, spat, topo);
}

//****************************************************************************
// Method:  avtPLYFileFormat::ReadInDataset
//
// Purpose:
//   Read in PLY file
// Programmer:  Dave Pugmire
// Creation:    April 16, 2013
//
// Modifications:
//
//****************************************************************************

void
avtPLYFileFormat::ReadInDataset(void)
{
    debug4 << "Reading in dataset from PLY file " << filename << endl;

    //
    // This shouldn't ever happen (since we would already have the dataset
    // we are trying to read from the file sitting in memory), but anything
    // to prevent leaks.
    //
    if (dataset != NULL)
    {
        dataset->Delete();
    }

    //
    // Create a file reader and set our dataset to be its output.
    //
    vtkPLYReader *reader = vtkPLYReader::New();
    //reader->SetStrict(GetStrictMode());
    reader->SetFileName(filename);
    reader->Update();
    dataset = reader->GetOutput();
    dataset->Register(NULL);

    reader->Delete();

    readInDataset = true;
}


// ****************************************************************************
//  Method: avtPLYFileFormat::GetMesh
//
//  Purpose:
//      Gets the mesh associated with this file.  The mesh is returned as a
//      derived type of vtkDataSet (ie vtkRectilinearGrid, vtkStructuredGrid,
//      vtkUnstructuredGrid, etc).
//
//  Arguments:
//      meshname    The name of the mesh of interest.  This can be ignored if
//                  there is only one mesh.
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

vtkDataSet *
avtPLYFileFormat::GetMesh(const char *meshname)
{
    debug5 << "Getting mesh from PLY file " << filename << endl;

    if (strcmp(meshname, "PLY_mesh") != 0)
    {
        EXCEPTION1(InvalidVariableException, meshname);
    }

    if (!readInDataset)
        ReadInDataset();

    dataset->Register(NULL);
    return dataset;
}


// ****************************************************************************
//  Method: avtPLYFileFormat::GetVar
//
//  Purpose:
//      Gets a scalar variable associated with this file.  Although VTK has
//      support for many different types, the best bet is vtkFloatArray, since
//      that is supported everywhere through VisIt.
//
//  Arguments:
//      varname    The name of the variable requested.
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

vtkDataArray *
avtPLYFileFormat::GetVar(const char *var)
{
    EXCEPTION1(InvalidVariableException, var);
}


// ****************************************************************************
//  Method: avtPLYFileFormat::GetVectorVar
//
//  Purpose:
//      Gets a vector variable associated with this file.  Although VTK has
//      support for many different types, the best bet is vtkFloatArray, since
//      that is supported everywhere through VisIt.
//
//  Arguments:
//      varname    The name of the variable requested.
//
//  Programmer: pugmire -- generated by xml2avt
//  Creation:   Tue Apr 16 08:57:58 PDT 2013
//
// ****************************************************************************

vtkDataArray *
avtPLYFileFormat::GetVectorVar(const char *var)
{
    EXCEPTION1(InvalidVariableException, var);
}
